package info.hexin.mvc;

import info.hexin.ioc.context.Ioc;
import info.hexin.ioc.context.impl.SimpleIoc;
import info.hexin.ioc.loader.impl.AnnotationLoader;
import info.hexin.lang.Strings;
import info.hexin.log.Log;
import info.hexin.log.Logs;
import info.hexin.mvc.config.Loading;
import info.hexin.mvc.handler.RequestHandler;
import info.hexin.mvc.handler.process.FileUploadRequestProcess;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.regex.Pattern;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.FilterRegistration;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 框架的入口
 * 
 * @author hexin
 * 
 */
public class WebFilter implements Filter {

    private static final Log log = Logs.get();

    private static final String IOC = "_ioc_name_";

    private static final String PACKAGES = "packages";
    private static final String XMLS = "xml";

    private static final String FILE_SPLIT = ",";
    private static final String EXCLUSION = "exclusion";
    private static final String DEFAULT_EXCLUSION = "^.+\\.(jsp|png|gif|jpg|js|css|jspx|jpeg|swf|ico)$";

    public List<String> startExclusionList = new ArrayList<String>();
    public List<String> endExclusionList = new ArrayList<String>();
    private Pattern exclusionPattern;
    public RequestHandler requestHandler;

    public void destroy() {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
            ServletException {
        HttpServletRequest servletRequest = (HttpServletRequest) request;
        HttpServletResponse servletResponse = (HttpServletResponse) response;
        String url = servletRequest.getRequestURI();

        // 是否托管到框架来处理
        if (exclusionPattern.matcher(url).find()) {
            chain.doFilter(request, response);
        } else {
            requestHandler.handler(servletRequest, servletResponse);
        }
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

        // 构造webioc容器
        createWebContext(filterConfig);

        // 系统参数
        initExclusionPattern(filterConfig);

        // 修改系统配置插件
        requestHandler = new RequestHandler();
        requestHandler.setFileUploadRequestProcess(new FileUploadRequestProcess());
    }

    private void initExclusionPattern(FilterConfig filterConfig) {
        String exclusions = filterConfig.getInitParameter(EXCLUSION);
        if (exclusions != null) {
            log.info("exclusion  >>>>> {}", exclusions);
            exclusionPattern = Pattern.compile(exclusions, Pattern.CASE_INSENSITIVE);
        } else {
            log.info("default exclusion  >>>>> {}", DEFAULT_EXCLUSION);
            exclusionPattern = Pattern.compile(DEFAULT_EXCLUSION, Pattern.CASE_INSENSITIVE);
        }
    }

    /**
     * 构造webioc容器，如果
     * 
     * @param filterConfig
     */
    private void createWebContext(FilterConfig filterConfig) {
        String filterName = filterConfig.getFilterName();

        FilterRegistration registration = filterConfig.getServletContext().getFilterRegistration(filterName);
        Collection<String> collectionMaping = registration.getUrlPatternMappings();
        log.info("filter maping >>>>> {}", collectionMaping);

        // 使用xml配置加载容器
        String xmls = filterConfig.getInitParameter(XMLS);
        if (Strings.isNotBlank(xmls)) {
            log.info("loading xmls file >>>>> {}", xmls);
        }

        // 合并ioc
        Ioc parent = null;
        Object object = filterConfig.getServletContext().getAttribute(IOC);
        if (object != null) {
            parent = (Ioc) object;
        }

        // 使用包来加载容器
        String packages = filterConfig.getInitParameter(PACKAGES);
        if (Strings.isNotBlank(packages)) {
            log.info("loading packages >>>>> {}", packages);
            Ioc ioc = new SimpleIoc(new AnnotationLoader(packages.split(FILE_SPLIT)));
            ioc.load(parent);
            filterConfig.getServletContext().setAttribute(IOC, ioc);
            try {
                Loading.scanWebAction(ioc, collectionMaping);
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }

    }
}
